home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / language / embedded / m68k / cc68k.arc / GENSTMT.C < prev    next >
C/C++ Source or Header  |  1989-09-27  |  13KB  |  398 lines

  1. #include        "stdio.h"
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *  all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or question
  18. s
  19.  *    to:
  20.  *
  21.  *        Matthew Brandt
  22.  *        Box 920337
  23.  *        Norcross, Ga 30092
  24.  */
  25.  
  26. int     breaklab;
  27. int     contlab;
  28. int     retlab;
  29.  
  30. extern TYP              stdfunc;
  31. extern struct amode     push[], pop[];
  32.  
  33. struct amode    *makedreg(r)
  34. /*
  35.  *      make an address reference to a data register.
  36.  */
  37. int     r;
  38. {       struct amode    *ap;
  39.         ap =(struct amode *)xalloc(sizeof(struct amode));
  40.         ap->mode = am_dreg;
  41.         ap->preg = r;
  42.         return ap;
  43. }
  44.  
  45. struct amode    *makeareg(r)
  46. /*
  47.  *      make an address reference to an address register.
  48.  */
  49. int     r;
  50. {       struct amode    *ap;
  51.         ap =(struct amode *)xalloc(sizeof(struct amode));
  52.         ap->mode = am_areg;
  53.         ap->preg = r;
  54.         return ap;
  55. }
  56.  
  57. struct amode    *make_mask(mask)
  58. /*
  59.  *      generate the mask address structure.
  60.  */
  61. int     mask;
  62. {       struct amode    *ap;
  63.         ap = (struct amode *)xalloc(sizeof(struct amode));
  64.         ap->mode = am_mask;
  65.         ap->offset =(struct enode *) mask;
  66.         return ap;
  67. }
  68.  
  69. struct amode    *make_direct(i)
  70. /*
  71.  *      make a direct reference to an immediate value.
  72.  */
  73. struct enode *i;
  74. {       return make_offset(makenode(en_icon,i,(struct enode *)0));
  75. }
  76.  
  77. struct amode    *make_strlab(s)
  78. /*
  79.  *      generate a direct reference to a string label.
  80.  */
  81. char    *s;
  82. {       struct amode    *ap;
  83.         ap = (struct amode *)xalloc(sizeof(struct amode));
  84.         ap->mode = am_direct;
  85.         ap->offset =(struct enode *) makenode(en_nacon,(struct enode *)s,
  86.                                                        (struct enode *)0);
  87.         return ap;
  88. }
  89.  
  90.  genwhile(stmt)
  91. /*
  92.  *      generate code to evaluate a while statement.
  93.  */
  94. struct snode    *stmt;
  95. {       int     lab1, lab2;
  96.         initstack();            /* initialize temp registers */
  97.         lab1 = contlab;         /* save old continue label */
  98.         lab2 = breaklab;        /* save old break label */
  99.         contlab = nextlabel++;  /* new continue label */
  100.         gen_label(contlab);
  101.         if( stmt->s1 != 0 )      /* has block */
  102.                 {
  103.                 breaklab = nextlabel++;
  104.                 initstack();
  105.                 falsejp(stmt->exp,breaklab);
  106.                 genstmt(stmt->s1);
  107.                 gen_code(op_bra,0,make_label(contlab),(struct amode *)0);
  108.                 gen_label(breaklab);
  109.                 breaklab = lab2;        /* restore old break label */
  110.                 }
  111.         else                            /* no loop code */
  112.                 {
  113.                 initstack();
  114.                 truejp(stmt->exp,contlab);
  115.                 }
  116.         contlab = lab1;         /* restore old continue label */
  117. }
  118.  
  119.  gen_for(stmt)
  120. /*
  121.  *      generate code to evaluate a for loop
  122.  */
  123. struct snode    *stmt;
  124. {       int     old_break, old_cont, exit_label, loop_label;
  125.         old_break = breaklab;
  126.         old_cont = contlab;
  127.         loop_label = nextlabel++;
  128.         exit_label = nextlabel++;
  129.         contlab = loop_label;
  130.         initstack();
  131.         if( stmt->label != 0 )
  132.                 gen_expr((struct enode *)(stmt->label),F_ALL | F_NOVALUE
  133.                         ,natural_size((struct enode *)stmt->label));
  134.         gen_label(loop_label);
  135.         initstack();
  136.         if( stmt->exp != 0 )
  137.                 falsejp(stmt->exp,exit_label);
  138.         if( stmt->s1 != 0 )
  139.         {
  140.                 breaklab = exit_label;
  141.                 genstmt(stmt->s1);
  142.         }
  143.         initstack();
  144.         if( stmt->s2 != 0 )
  145.                 gen_expr((struct enode *)stmt->s2,F_ALL | F_NOVALUE,natural_size((struct enode *)stmt->s2));
  146.         gen_code(op_bra,0,make_label(loop_label),(struct amode *)0);
  147.         breaklab = old_break;
  148.         contlab = old_cont;
  149.         gen_label(exit_label);
  150. }
  151.  
  152.  genif(stmt)
  153. /*
  154.  *      generate code to evaluate an if statement.
  155.  */
  156. struct snode    *stmt;
  157. {       int     lab1, lab2, oldbreak;
  158.         lab1 = nextlabel++;     /* else label */
  159.         lab2 = nextlabel++;     /* exit label */
  160.         oldbreak = breaklab;    /* save break label */
  161.         initstack();            /* clear temps */
  162.         falsejp(stmt->exp,lab1);
  163.         if( stmt->s1 != 0 && stmt->s1->next != 0 )
  164.                 if( stmt->s2 != 0 )
  165.                         breaklab = lab2;
  166.                 else
  167.                         breaklab = lab1;
  168.         genstmt(stmt->s1);
  169.         if( stmt->s2 != 0 )             /* else part exists */
  170.                 {
  171.                 gen_code(op_bra,0,make_label(lab2),(struct amode *)0);
  172.                 gen_label(lab1);
  173.                 if( stmt->s2 == 0 || stmt->s2->next == 0 )
  174.                         breaklab = oldbreak;
  175.                 else
  176.                         breaklab = lab2;
  177.                 genstmt(stmt->s2);
  178.                 gen_label(lab2);
  179.                 }
  180.         else                            /* no else code */
  181.                 gen_label(lab1);
  182.         breaklab = oldbreak;
  183. }
  184.  
  185.  gendo(stmt)
  186. /*
  187.  *      generate code for a do - while loop.
  188.  */
  189. struct snode    *stmt;
  190. {       int     oldcont, oldbreak;
  191.         oldcont = contlab;
  192.         oldbreak = breaklab;
  193.         contlab = nextlabel++;
  194.         gen_label(contlab);
  195.         if( stmt->s1 != 0 && stmt->s1->next != 0 )
  196.                 {
  197.                 breaklab = nextlabel++;
  198.                 genstmt(stmt->s1);      /* generate body */
  199.                 initstack();
  200.                 truejp(stmt->exp,contlab);
  201.                 gen_label(breaklab);
  202.                 }
  203.         else
  204.                 {
  205.                 genstmt(stmt->s1);
  206.                 initstack();
  207.                 truejp(stmt->exp,contlab);
  208.                 }
  209.         breaklab = oldbreak;
  210.         contlab = oldcont;
  211. }
  212.  
  213.  call_library(lib_name)
  214. /*
  215.  *      generate a call to a library routine.
  216.  */
  217. char    *lib_name;
  218. {       SYM     *sp;
  219.         sp = (SYM *)gsearch(lib_name);
  220.         if( sp == 0 )
  221.                 {
  222.                 ++global_flag;
  223.                 sp =(SYM *) xalloc(sizeof(SYM));
  224.                 sp->tp = &stdfunc;
  225.                 sp->name = lib_name;
  226.                 sp->storage_class = sc_external;
  227.                 insert(sp,&gsyms);
  228.                 --global_flag;
  229.                 }
  230.         gen_code(op_jsr,0,make_strlab(lib_name),(struct amode *)0);
  231. }
  232.  
  233.  genswitch(stmt)
  234. /*
  235.  *      generate a linear search switch statement.
  236.  */
  237. struct snode    *stmt;
  238. {       int             curlab;
  239.         struct snode    *defcase;
  240.         struct amode    *ap;
  241.         curlab = nextlabel++;
  242.         defcase = 0;
  243.         initstack();
  244.         ap =(struct amode *) gen_expr(stmt->exp,F_DREG | F_VOL,4);
  245.         if( ap->preg != 0 )
  246.                 gen_code(op_move,4,ap,makedreg(0));
  247.         stmt = stmt->s1;
  248.     call_library("_C_SWITCH");
  249.         while( stmt != 0 )
  250.                 {
  251.                 if( stmt->s2 )          /* default case ? */
  252.                         {
  253.                         stmt->label =(int *) curlab;
  254.                         defcase = stmt;
  255.                         }
  256.                 else
  257.                         {
  258.                         gen_code(op_dc,4,make_label(curlab),
  259.                                 make_direct((struct enode *)stmt->label));
  260.                         stmt->label =(int *) curlab;
  261.                         }
  262.                 if( stmt->s1 != 0 && stmt->next != 0 )
  263.                         curlab = nextlabel++;
  264.                 stmt = stmt->next;
  265.                 }
  266.         if( defcase == 0 )
  267.                 gen_code(op_dc,4,make_direct((struct enode *)0),
  268.                                  make_label(breaklab));
  269.         else
  270.                 gen_code(op_dc,4,make_direct((struct enode *)0),
  271.                                  make_label((int)defcase->label));
  272. }
  273.  
  274.  gencase(stmt)
  275. /*
  276.  *      generate all cases for a switch statement.
  277.  */
  278. struct snode    *stmt;
  279. {       while( stmt != 0 )
  280.                 {
  281.                 if( stmt->s1 != 0 )
  282.                         {
  283.                         gen_label((int)stmt->label);
  284.                         genstmt(stmt->s1);
  285.                         }
  286.                 else if( stmt->next == 0 )
  287.                         gen_label((int)stmt->label);
  288.                 stmt = stmt->next;
  289.                 }
  290. }
  291.  
  292.  genxswitch(stmt)
  293. /*
  294.  *      analyze and generate best switch statement.
  295.  */
  296. struct snode    *stmt;
  297. {       int     oldbreak;
  298.         oldbreak = breaklab;
  299.         breaklab = nextlabel++;
  300.         genswitch(stmt);
  301.         gencase(stmt->s1);
  302.         gen_label(breaklab);
  303.         breaklab = oldbreak;
  304. }
  305.  
  306.  genreturn(stmt)
  307. /*
  308.  *      generate a return statement.
  309.  */
  310. struct snode    *stmt;
  311. {       struct amode    *ap;
  312.         if( stmt != 0 && stmt->exp != 0 )
  313.                 {
  314.                 initstack();
  315.                 ap =(struct amode *) gen_expr(stmt->exp,F_ALL,4);
  316.                 if( ap->mode != am_dreg || ap->preg != 0 )
  317.                         gen_code(op_move,4,ap,makedreg(0));
  318.                 }
  319.         if( retlab == -1 )
  320.                 {
  321.                 retlab = nextlabel++;
  322.                 gen_label(retlab);
  323.                 if( save_mask != 0 )
  324.                         gen_code(op_movem,4,pop,make_mask(save_mask));
  325.                 gen_code(op_unlk,0,makeareg(6),(struct amode *)0);
  326.                 gen_code(op_rts,0,(struct amode *)0,(struct amode *)0);
  327.                 }
  328.         else
  329.                 gen_code(op_bra,0,make_label(retlab),(struct amode *)0);
  330. }
  331.  
  332.  genstmt(stmt)
  333. /*
  334.  *      genstmt will generate a statement and follow the next pointer
  335.  *      until the block is generated.
  336.  */
  337. struct snode    *stmt;
  338. {       while( stmt != 0 )
  339.                 {
  340.                 switch( stmt->stype )
  341.                         {
  342.                         case st_label:
  343.                                 gen_label((int)stmt->label);
  344.                                 break;
  345.                         case st_goto:
  346.                                 gen_code(op_bra,0,make_label((int)stmt->label),
  347.                                                    (struct amode *)0);
  348.                                 break;
  349.                         case st_expr:
  350.                                 initstack();
  351.                                 gen_expr(stmt->exp,F_ALL | F_NOVALUE,
  352.                                         natural_size(stmt->exp));
  353.                                 break;
  354.                         case st_return:
  355.                                 genreturn(stmt);
  356.                                 break;
  357.                         case st_if:
  358.                                 genif(stmt);
  359.                                 break;
  360.                         case st_while:
  361.                                 genwhile(stmt);
  362.                                 break;
  363.                         case st_for:
  364.                                 gen_for(stmt);
  365.                                 break;
  366.                         case st_continue:
  367.                                 gen_code(op_bra,0,make_label(contlab),
  368.                                                   (struct amode *)0);
  369.                                 break;
  370.                         case st_break:
  371.                                 gen_code(op_bra,0,make_label(breaklab),
  372.                                                   (struct amode *)0);
  373.                                 break;
  374.                         case st_switch:
  375.                                 genxswitch(stmt);
  376.                                 break;
  377.                         default:
  378.                                 printf("DIAG - unknown statement.\n");
  379.                                 break;
  380.                         }
  381.                 stmt = stmt->next;
  382.                 }
  383. }
  384.  
  385.  genfunc(stmt)
  386. /*
  387.  *      generate a function body.
  388.  */
  389. struct snode    *stmt;
  390. {       retlab = contlab = breaklab = -1;
  391.         if( lc_auto & 1 )    /* if frame size odd */
  392.             ++lc_auto;        /* make it even */
  393.         gen_code(op_link,0,makeareg(6),make_immed(-lc_auto));
  394.         opt1(stmt);
  395.         genstmt(stmt);
  396.         genreturn((struct snode *)0);
  397. }
  398.